<script setup>
import ol from "@/utils/ol";
import { plot } from "@comp/ol/plotting/plotting";

let map, iDraw, plottingLayer;

const iActType = ref();
const iType = ref(); // 当前绘制的军标类型
const strokeWidth = ref(2); // 军标线宽
const plot_geometries = ref([]); // 临时生成对象[polygon,linestring,...] 临时绘制图形使用
const currColor = ref("#FF0000"); // 绘制线颜色

const initMap = () => {
  const tk = "fb854e7c9218a0d4903e4c765df3fa63";
  const baseLayer = new ol.layer.Tile({
    source: new ol.source.XYZ({
      maxZoom: 18,
      url: `http://t4.tianditu.com/DataServer?T=vec_w&tk=${tk}&x={x}&y={y}&l={z}`,
      crossOrigin: "anonymous",
    }),
    name: "矢量地图",
  });
  const zjLayer = new ol.layer.Tile({
    source: new ol.source.XYZ({
      maxZoom: 18,
      url: `http://t4.tianditu.com/DataServer?T=cva_w&tk=${tk}&x={x}&y={y}&l={z}`,
      crossOrigin: "anonymous",
    }),
    name: "矢量注记",
  });
  map = new ol.Map({
    view: new ol.View({
      projection: "EPSG:4326",
      center: [121.43, 37.45],
      zoom: 10,
    }),
    layers: [baseLayer, zjLayer],
    target: "map",
  });
  window.map = map;
};

const initPlottingLayer = () => {
  const defStyle = new ol.style.Style({
    fill: new ol.style.Fill({
      color: "rgba(255,0,0,0.4)",
    }),
    stroke: new ol.style.Stroke({
      color: "#e21e0a",
      width: strokeWidth.value, // 2
    }),
    image: new ol.style.Circle({
      radius: 5,
      fill: new ol.style.Fill({
        color: "#ff0000",
      }),
    }),
    text: new ol.style.Text({
      fill: new ol.style.Fill({
        // 文字填充色
        color: "#ff0000",
      }),
      stroke: new ol.style.Stroke({
        // 文字边界宽度与颜色
        color: "rgba(255,0,0,0)",
        width: 1,
      }),
    }),
  });

  plottingLayer = new ol.layer.Vector({
    source: new ol.source.Vector(), // ol.source.Vector 用来保存标绘
    wrapX: false,
    style: defStyle,
  });
  map.addLayer(plottingLayer);
};

const lineClick = () => {
  const obj = {
    key: "mult_getMotorLine",
    label: "实心虚线箭头",
    方法: "是",
  };
  selectPlot(obj.key);
};

const selectPlot = (plotID) => {
  iActType.value = plotID;
  setPlotType(plotID); // 修改plottingLayer.iType;触发draw事件绘制
  console.log(window);
};

/* Method: setPlotType
 * 设置军标类型
 * 参数 pType：军标类型或军标ID
 * 返回：
 */
const setPlotType = (pType) => {
  iType.value = pType;
  iTypeWatch();
};

// 删除draw 重新添加draw
const iTypeWatch = () => {
  map.removeInteraction(iDraw);
  addInteraction();
};

/*
 * parseGeometry
 * 生成绘制方法所需的geometry数据;drawend生成GeometryCollection对象使用！
 * 参数cData(coordinate point data)通过绘制方法生成的点数据, 如：{geoType:整体类型，geoData[{gid:123,type:LineSting,data[],style:{}},...]}
 * 返回：geometries数组，每个元素是一个geometry对象（线，面等），如：[polygon,linestring,...]
 */
const parseGeometry = (cData) => {
  const geometries = []; // 保存每个绘制图形的对象
  if (cData.geoType === "GeometryCollection") {
    for (let i = 0; i < cData.geoData.length; i++) {
      // 获取返回结果查看是否有属性
      let iStyle = cData.geoData[i]?.style;
      if (!iStyle) {
        iStyle = {
          fill: null,
          stroke: currColor.value,
          width: "2px",
        };
      }
      // 根据类型设置数据（目前只有Polygon，LineString，Text）
      const geometry = new ol.geom.LineString(cData.geoData[i].data);
      geometries.push(geometry);
    } // end for
    return geometries;
  }
};

const addInteraction = () => {
  let value = iType.value;
  let iMaxPoints = null;
  if (!value) return; // 没有绘制样式时推出(null就返回)
  if (value.length < 4) return; // 长度不满足要求不做处理
  const funName = iType.value.split("_")[1];
  value = "LineString";
  const func = plot.getFunc(funName);
  // 开始绘制箭头类形军标
  const geometryFunction = (coordinates, geometry) => {
    // 返回绘制箭头所需的--几何元素
    plot_geometries.value = func(coordinates); // 返回组成军标的所有数据[geoType:xx,geoData:[{图元1},{图元2}...];但是图元信息不全
    const geometryList = parseGeometry(plot_geometries.value); // 返回生成的geometry如：[polygon,linestring,...] 提供给下面生成geometrycollection
    // 所有绘制plot均视为GeometryCollection
    if (!geometry) {
      geometry = new ol.geom.GeometryCollection(geometryList);
    } else {
      geometry.setGeometries(geometryList);
    }
    // 绘制临时图像-drawend中写入军标绘制层
    return geometry;
  };
  iDraw = new ol.interaction.Draw({
    type: value,
    maxPoints: iMaxPoints,
    geometryFunction,
  });
  map.addInteraction(iDraw);
  // let listener
  // 绘制开始事件
  iDraw.on("drawstart", (evt) => {
    console.log(evt);
  });
  // 绘制结束事件
  iDraw.on("drawend", (evt) => {
    const idStr = iActType.value + "_" + new Date().valueOf();
    // 处理基本图形数据
    // 箭头类型
    // 箭头处理，和SVG方式应该一致
    // 需要补全图元缺失部分
    const iStyle = {
      fill: "none", // currColor.value,
      stroke: currColor.value,
      width: strokeWidth.value, // 2
    };
    console.log(plot_geometries.value)
    for (let i = 0; i < plot_geometries.value.geoData.length; i++) {
      plot_geometries.value.geoData[i].gid = idStr;
      plot_geometries.value.geoData[i].style = JSON.parse(
        JSON.stringify(iStyle)
      );
    }

    // 实心箭头和虚线箭头样式设置（需要调整-见下面）
    if (
      iActType.value === "mult_getSSArrowPnts" ||
      iActType.value === "mult_dashArrowPnts" ||
      iActType.value === "mult_pathArrowPnts" ||
      iActType.value === "mult_dashPathArrowPnts"
    ) {
      plot_geometries.value.geoData[0].style.fill = currColor.value;
      plot_geometries.value.geoData[0].style.width = 0;
    }

    // 新添加的带轮线（箭头要填充！）
    if (iActType.value === "mult_getCyyLine") {
      // 组成图形的顺序[箭头多边形，主曲线，辅助曲线，圆轮xn]
      plot_geometries.value.geoData[0].style.fill = currColor.value;
      plot_geometries.value.geoData[0].style.width = 0;
      plot_geometries.value.geoData[2].style.stroke = "#000000";
      plot_geometries.value.geoData[2].color = "#000000";
    }
    // 摩托化行进
    if (iActType.value === "mult_getMotorLine") {
      // 组成图形的顺序[箭头多边形，主曲线，辅助曲线，圆轮xn]
      plot_geometries.value.geoData[0].style.fill = currColor.value;
      plot_geometries.value.geoData[0].style.width = 0;
    }
    // 伴随线
    if (iActType.value === "mult_getFollowLine") {
      // 组成图形的顺序[箭头多边形，主曲线，辅助曲线，圆轮xn]
      plot_geometries.value.geoData[0].style.fill = currColor.value;
      plot_geometries.value.geoData[0].style.width = 0;
      plot_geometries.value.geoData[2].style.stroke = "#DEB887";
    }

    // 虚线的处理
    if (
      iActType.value === "mult_dashArrowPnts" ||
      iActType.value === "mult_dashPathArrowPnts"
    ) {
      plot_geometries.value.geoData[1].style.lineDash = [20, 10];
    }
    // 将标绘图形加入标绘层
    geom2Featrue();
    // 标绘停止
    endPlotting();
  });
};

// 结束本次军标绘制，等待新的开始
const endPlotting = () => {
  iType.value = null;
  iTypeWatch();
};

/*
 * Method：geom2Featrue
 * 将从getFeature获得的数据{geoType:x.geoData:[{gid,type,data,style},{},...]}添加到标绘层
 * 参数：gData：{geoType:x.geoData:[{gid,type,data,style},{},...]}
 */
// 带文字旋转 参数：sSRS表示数据的坐标格式（所有标绘操作都已'EPSG:3857'为准）
const geom2Featrue = (plotData = plot_geometries.value) => {
  if (!plotData) return;
  const gType = plotData.geoType;
  const gData = plotData.geoData;
  let iGeom = null;
  let iFeature = null;
  if (gType === "GeometryCollection") {
    for (let i = 0; i < gData.length; i++) {
      const gID = gData[i].gid;
      let iType = gData[i].type;
      const iData = gData[i].data;
      const iStyle = gData[i].style;
      let newStyle = null;
      iType = iType.toLowerCase();
      // 处理多边形
      if (iType === "polygon") {
        iGeom = new ol.geom.Polygon(iData);
        iFeature = new ol.Feature(iGeom);
        iFeature.set("gid", gID);
        iFeature.set("type", "PLOT");
        // 属性创建
        // 多边形有填充色-2
        // 多边形有填充色，非固有色。使用当前颜色2-1
        // 填充色为固有色 2-2
        const iFill = iStyle.fill;
        let strokeColor = iStyle.stroke;
        const iWidth = iStyle.width;
        // 获取勾边宽度，没有或为0，表示没有勾边
        if (!iWidth) {
          strokeColor = null;
        }
        // 勾边色为空，只有填充；无勾边 2-2-1
        newStyle = new ol.style.Style({
          fill: new ol.style.Fill({
            color: iFill,
          }),
        });

        // 设置虚线--如果设置了style.lineDash参数需要设置虚线
        if (iStyle.lineDash) {
          const iStroke = newStyle.getStroke();
          iStroke.setLineDash(iStyle.lineDash);
        }
        // 属性添加到Featrue
        iFeature.setStyle(newStyle);
      }
      if (iType === "linestring") {
        iGeom = new ol.geom.LineString(iData);
        iFeature = new ol.Feature(iGeom);
        // 需要添加控制点属性--待添加
        iFeature.set("gid", gID);
        iFeature.set("type", "PLOT");
        // 属性创建
        let strokeColor = iStyle.stroke;
        if (!strokeColor) {
          // 勾边色为空，设置为当前色
          strokeColor = currColor.value;
        }
        // 有勾边色，设置多边形为描边样式，边的颜色如果不是固有色，替换成当前色： B-1
        // B-2 勾边为固有色，勾边色保持不变！
        newStyle = new ol.style.Style({
          stroke: new ol.style.Stroke({
            color: strokeColor,
            width: iStyle.width ? iStyle.width : 2,
          }),
        });
        // 设置虚线--如果设置了style.lineDash参数需要设置虚线
        if (iStyle.lineDash) {
          const iStroke = newStyle.getStroke();
          iStroke.setLineDash(iStyle.lineDash);
        }
        // 属性添加到Featrue
        iFeature.setStyle(newStyle);
      }
      if (iType === "point") {
        iGeom = new ol.geom.Point(iData[0]);
        iFeature = new ol.Feature(iGeom);
        iFeature.set("gid", gID);
        iFeature.set("type", "PLOT");
        let txtRot;
        if (iStyle.rotate) {
          txtRot = iStyle.rotate;
        } else {
          txtRot = 0;
        }
        // 创建样式
        newStyle = new ol.style.Style({
          text: new ol.style.Text({
            // 位置
            textAlign: "left", // 'left', 'right', 'center', 'end' or 'start'.
            // 基准线
            textBaseline: "middle", // 'bottom', 'top', 'middle', 'alphabetic', 'hanging', 'ideographic'.
            // 文字样式
            font: iStyle.font, // 默认格式 'normal 14px 微软雅黑',
            // font: 'normal' + x + 'px 微软雅黑',
            // 文本内容
            text: iStyle.txt,
            scale: iData[1][0], // 文字数据信息[[点的地理坐标x， y]，[文字的缩放*，文字的旋转]]
            rotation: txtRot,
            // 文字旋转
            // 文本填充样式（即文字颜色）
            fill: new ol.style.Fill({ color: "#000000" }),
            stroke: new ol.style.Stroke({ color: "#FFFFFF", width: 1 }),
          }),
        });
        // 属性添加到Featrue
        iFeature.setStyle(newStyle);
      }
      // 绘制cyy添加的circle
      if (iType === "circle") {
        // 获得两个控制点
        const cp1 = iData[0];
        const cp2 = iData[1];
        // 求两个点的距离(半径)--可能需要进行坐标转换，转换到3857，计算长度。（坐标转换）
        const r = plot.CalLengthOfTwoPoints(cp1, cp2);
        // 绘制圆--new Circle(center, opt_radius)
        iGeom = new ol.geom.Circle(cp1, r); // 生成圆
        iFeature = new ol.Feature(iGeom); // 生成feature
        // 需要添加控制点属性--待添加
        iFeature.set("gid", gID);
        iFeature.set("type", "PLOT");
        // 没有填充颜色-1
        let strokeColor = iStyle.stroke;
        // 有勾边色，设置多边形为描边样式，边的颜色如果不是固有色，替换成当前色： B-1
        // B-2 勾边为固有色，勾边色保持不变！
        newStyle = new ol.style.Style({
          fill: new ol.style.Fill({
            color: "rgba(0,0,0,0)",
          }),
          stroke: new ol.style.Stroke({
            color: strokeColor,
            width: iStyle.width ? iStyle.width : 0,
          }),
        });
      }

      // 设置虚线--如果设置了style.lineDash参数需要设置虚线
      if (iStyle.lineDash) {
        const iStroke = newStyle.getStroke();
        iStroke.setLineDash(iStyle.lineDash);
      }
      // 属性添加到Featrue
      iFeature.setStyle(newStyle);
      plottingLayer.getSource().addFeature(iFeature);
    }
  }
};
onMounted(() => {
  initMap();
  initPlottingLayer();
});
</script>
<template>
  <div id="map"></div>
  <div class="btns">
    <el-button type="primary" @click="lineClick">虚线箭头</el-button>
  </div>
</template>
<style lang="scss" scoped>
#map {
  width: 100%;
  height: 100vh;
}

.btns {
  position: absolute;
  left: 40px;
  top: 20px;
}
</style>
